/**
 * @file ringflow.h
 *
 * @brief Ring buffers
 *
 * Ringbuffer implementation store/access arbitrary binary data
 * 
 * author : zhangerhu
 *
 */
#ifndef _RINGFLOW_H_
#define _RINGFLOW_H_

#ifdef __cplusplus
extern "C" {
#endif

#define BUF_USED     0Xff000000
#define BUF_FREE     0X00000000
#define RBUF_ALIGN   4

typedef enum
{
    RBUF_MODE_BUF_IN = 0,
    RBUF_MODE_BUF_OUT
} rbuf_mode_t;

typedef enum
{
    RBUF_MODE_SIMPLE = 0,
    RBUF_MODE_SHARE
} rbuf_run_mode_t;


typedef enum
{
    RBUF_CREATE_SERVER_ROLE = 0,
    RBUF_CREATE_CLIENT_ROLE
} rbuf_create_role;

struct _ring_flow_s
{
    char *buf;          // the buffer
    char *buf_s;
    char *buf_c;
    int block_size;     // block size
    int block_count;    // block count
    int size;           // buffer size
    int used;           // used size
    int rfx;            // read offset
    int wfx;            // write offset
    int mode;           // out buffer mode
    int run_mode;       // run mode
    int role;           // create role
};

/**
 * @brief ringbuffer handler
 */
typedef struct _ring_flow_s rflow_t;

/**
 * @brief Create a new ringbuffer, buffer size is (block_size * block_count)
 * @param buf : A block of memory in a ring buffer that, if empty, internally requests a cache of its own (in bytes)
 * @param block_size  : The size of a cache in a ring buffer (in bytes)
 * @param block_count : The number of caches in the ring buffer
 * @param mode        : The buffer mode, RBUF_MODE_BUF_IN or RBUF_MODE_BUF_OUT
 * @param role        : The create role, RBUF_CREATE_SERVER_ROLE or RBUF_CREATE_CLIENT_ROLE
 * @return : A pointer to an initialized rflow_t structure
 */
rflow_t *rbuf_create(char *buf, int block_size, int block_count, int mode, int role);

/**
 * @brief Write the specified amount of bytes into the ringbuffer
 * @param rbuf  : A valid pointer to a rbuf_t structure
 * @param in   : A pointer to the data to copy into the ringbuffer
 * @param size : The amount of bytes to be copied
 * @return     : The amount of bytes actually copied into the ringbuffer
 */
int rbuf_write(rflow_t* rbuf, char *data, int len);

/**
 * @brief Read the specified amount of bytes from the ringbuffer
 * @param rbuf  : A valid pointer to a rbuf_t structure
 * @param out  : A valid pointer initialized to store the read data
 * @param size : The amount of bytes to read and copy to the memory
 *               pointed by 'buf'
 * @return     : The amount of bytes actually read from the ringbuffer
 */
int rbuf_read(rflow_t* rbuf, char *out, int len);

/**
 * @brief Read the specified amount of bytes from the ringbuffer
 * @param rbuf  : A valid pointer to a rbuf_t structure
 * @param out  : A valid pointer initialized to store the read data
 * @param size : The amount of bytes to read and copy to the memory
 *               pointed by 'buf'
 * @param post : The offset of ringbuffer
 * @return     : The amount of bytes actually read from the ringbuffer
 */
int rbuf_read_post(rflow_t* rbuf, char *out, int len, int* post);

/**
 * @brief Release all resources associated to the rbuf_t structure
 * @param rbuf : A valid pointer to a rflow_t structure
 * @note： The external buffer must be released by the applicant
 */
void rbuf_destroy(rflow_t* rbuf);

#ifdef __cplusplus
}
#endif


#endif